package com.two.screen.water.balance.net.api

import com.two.screen.water.balance.bean.BaseBean
import com.two.screen.water.balance.bean.database.*
import com.two.screen.water.balance.listener.ApiCallBack
import com.two.screen.water.balance.listener.MyObserver
import com.two.screen.water.balance.net.observer.DialogObserver
import com.two.screen.water.balance.ui.App
import com.two.screen.water.balance.ui.activity.base.BaseActivity
import com.two.screen.water.balance.utils.*
import io.reactivex.Observable
import io.reactivex.ObservableOnSubscribe
import org.greenrobot.greendao.query.WhereCondition
import java.math.BigDecimal

object OrderApi {

    /*订单类型状态*/ //0未支付;1支付中;2已支付;3退货;4反结账;
    //val ORDER_STATUS_NO_PAY = 0 //0未支付; 应该不存在
    val ORDER_STATUS_PAYING = 1 //1支付中
    val ORDER_STATUS_PAID = 2 //2已支付
    val ORDER_STATUS_RETURN = 3 //3退货
    val ORDER_STATUS_REVERSE_CHECKOUT = 4 //4反结账

    /*订单类型状态*/
    val ORDER_TYPE_NORMAL = 0 //0正常订单
    val ORDER_TYPE_PENDING = 1 //1挂单

    /*订单支付类型状态*/
    val PAY_TYPE_NONE = -1 //-1 未选
    val PAY_TYPE_CASH = 0 //0 现金
    val PAY_TYPE_WETCH_VIP = 1 //1 微会员
    val PAY_TYPE_JUHE = 2 //2 聚合支付
    val PAY_TYPE_VIP_CARD = 3 //会员卡
    val PAY_TYPE_SCAN_QR = 4 //扫码盒子 键盘输入 扫客户的支付码

    /*这里通过登录返回的pay_id来转成本地payType*/
    fun getLocalPayType(serverPayType: Int): Int {
        return when (serverPayType) {
            1 -> PAY_TYPE_CASH
            2 -> PAY_TYPE_WETCH_VIP
            3 -> PAY_TYPE_VIP_CARD
            4 -> PAY_TYPE_JUHE
            5 -> PAY_TYPE_SCAN_QR
            else -> 0
        }
    }

    fun createOrderDB(findZero: Double, discountPercent: Int, totalPrice: Double, realPrice: Double, payType: Int, payTypeName: String, orderType: Int): OrderDB {
        var orderDB = OrderDB().apply {
            this.orderSn = CommUtils.getOrderSn()
            this.totalPrice = String.format("%.2f", totalPrice)
            this.realPrice = String.format("%.2f", realPrice)
            this.findZero = String.format("%.2f", findZero)

            this.payType = payType.toString()
            this.payTypeName = payTypeName
            this.vipCode = null
            this.deviceSn = DataApi.mAppUnitId
            this.payTime = System.currentTimeMillis() / 1000
            this.payTimeName = CommUtils.toYMD(this.payTime, "yyyy-MM-dd HH:mm:ss")
            this.createTime = this.payTime
            this.createTimeName = CommUtils.toYMD(this.createTime, "yyyy-MM-dd HH:mm:ss")

            this.userName = DataApi.mUserName
            this.userId = DataApi.mUserId
            this.discountPercent = discountPercent
            //TODO:这里可能还需要计算整单优惠
            this.giftPrice = String.format("%.2f", totalPrice * (100 - discountPercent) / 100.0)//这里针对整单优惠来说，与单个商品优惠无关。
            this.token
            this.orderType = orderType //订单类型：0正常订单;1挂单。
            this.integralUrl = "https://yccapi.jzxnm.com/order/${this.orderSn}"//默认二维码是：域名+订单号
        }

        return orderDB
    }

    /*更新订单信息*/
    fun updateOrderDB(orderDB: OrderDB, findZero: Double, discountPercent: Int, totalPrice: Double, realPrice: Double, payType: Int, payTypeName: String, orderType: Int) {
        orderDB.totalPrice = String.format("%.2f", totalPrice)
        orderDB.realPrice = String.format("%.2f", realPrice)
        orderDB.findZero = String.format("%.2f", findZero)

        orderDB.payType = payType.toString()
        orderDB.payTypeName = payTypeName
        orderDB.orderType = orderType //订单类型：0正常订单;1挂单。
        orderDB.discountPercent = discountPercent
        orderDB.giftPrice = String.format("%.2f", totalPrice * (100 - discountPercent) / 100.0)//这里针对整单优惠来说，与单个商品优惠无关。
        orderDB.payTime = System.currentTimeMillis() / 1000
        orderDB.payTimeName = CommUtils.toYMD(orderDB.payTime, "yyyy-MM-dd HH:mm:ss")
        App.mDaoSession?.orderDBDao?.insertOrReplace(orderDB)
    }

    fun getPayTypeName(payType: Int) = when (payType) {
        //0现金   1微会员    2聚合支付
        PAY_TYPE_NONE -> "未选"
        PAY_TYPE_CASH -> "现金"
        PAY_TYPE_WETCH_VIP -> "微会员"
        PAY_TYPE_JUHE -> "聚合支付"
        PAY_TYPE_VIP_CARD -> "微会卡"
        PAY_TYPE_SCAN_QR -> "扫码收款"
        else -> "未知"
    }

    fun saveOrderDB(orderDB: OrderDB, goodsList: MutableList<OrderProductDB>?) {
        //这里是保存订单到数据库
        App.mDaoMaster?.newSession()?.callInTx {
            //App.mDaoMaster?.newSession()?.orderDBDao?.insert(orderDB)
            App.mDaoSession?.orderDBDao?.insertOrReplace(orderDB)
            val userId = DataApi.mUserId
            //TODO:先处理商品
            d("订单ID是否生效：${orderDB.id}")
            //d("saveOrderDB->goodsList:${CommUtils.gson.toJson(goodsList)}")
            var totalWeight = 0.0
            var giftPrice = BigDecimal(0.00)

            goodsList?.forEach {
                var data = CommUtils.gson.fromJson(CommUtils.gson.toJson(it), OrderProductDB::class.java)
                data.id = null //因为这里从ProductDB转换过来的
                data.orderId = orderDB.id
                data.createTime = System.currentTimeMillis() / 1000
                data.createTimeName = CommUtils.toYMD_HMS(data.createTime)
                data.userId = userId
                totalWeight += try {
                    it.weight?.toDouble() ?: 0.0
                } catch (e: Exception) {
                    0.0
                }
                giftPrice = try {
                    val d1 = it.giftPrice.toDouble()
                    UtilsBigDecimal.add(giftPrice, d1)
                } catch (e: Exception) {
                    BigDecimal(0.00)
                }
                App.mDaoSession?.orderProductDBDao?.insertOrReplace(data)
            }
            orderDB.totalWeight = String.format("%.3f", totalWeight)
            orderDB.totalGiftPrice = String.format("%.2f", giftPrice.toDouble())
            App.mDaoSession?.orderDBDao?.update(orderDB)
        }
    }

//    fun queryOrderDBList(baseActivity: BaseActivity, apiCallBack: ApiCallBack? = null){
//        Observable.create(ObservableOnSubscribe<String> { e ->
//            val orderDBList = App.mDaoMaster?.newSession()?.queryBuilder(OrderDB::class.java)
//                ?.where(OrderDBDao.Properties.OrderType.eq(ORDER_TYPE_NORMAL))
//                ?.list()
//        })
//            .compose(RxUtils.io())
//            .compose(RxUtils.aLifecycle(baseActivity))
//            .subscribe(object : MyObserver<String>() {
//                override fun onNext(t: String) {
//                    apiCallBack?.success(t)
//                }
//
//                override fun onError(t: Throwable) {
//                    ToastUtil.showToast(t.message.toString())
//                    apiCallBack?.fail(t)
//                }
//            })
//    }

    //更新挂单操作
    fun updatePendingOrder(baseActivity: BaseActivity, mPendingOrder: OrderDB?, hadChooseList: MutableList<OrderProductDB>?, apiCallBack: ApiCallBack? = null) {
        Observable.create(ObservableOnSubscribe<String> { e ->
            try {
                App.mDaoSession?.callInTx {
                    //d("mPendingOrder.id:${mPendingOrder?.id}")
                    mPendingOrder?.isSelected = false
                    App.mDaoSession?.orderDBDao?.update(mPendingOrder)
                    //先查出改订单以前关联的商品
                    var deleteList = App.mDaoSession?.orderProductDBDao?.queryBuilder()?.where(OrderProductDBDao.Properties.OrderId.eq(mPendingOrder?.id))?.list()
                    deleteList?.forEach {
                        //然后逐个删除掉
                        //d("deleteList:${CommUtils.gson.toJson(it)}")
                        App.mDaoSession?.orderProductDBDao?.delete(it)
                    }
                    //最后重新添加关联此订单
                    hadChooseList?.forEach {
                        it.id = null
                        it.orderId = mPendingOrder?.id
                        //d("hadChooseList:${CommUtils.gson.toJson(it)}")
                        App.mDaoSession?.orderProductDBDao?.insert(it)
                    }
                    e.onNext("操作成功!")
                }
            } catch (exe: Exception) {
                d("操作失败:${exe}")
                e.onError(Throwable("操作失败：$exe"))
            }
        })
            .compose(RxUtils.io())
            .compose(RxUtils.aLifecycle(baseActivity))
            .subscribe(object : MyObserver<String>() {
                override fun onNext(t: String) {
                    apiCallBack?.success(t)
                }

                override fun onError(t: Throwable) {
                    ToastUtil.showToast(t.message.toString())
                    apiCallBack?.fail(t)
                }
            })
    }

    //移除挂单。
    fun removePendingOrder(baseActivity: BaseActivity, mPendingOrder: OrderDB?, apiCallBack: ApiCallBack? = null) {
        Observable.create(ObservableOnSubscribe<String> { e ->
            try {
                App.mDaoSession?.callInTx {
                    //先查出改订单以前关联的商品
                    var deleteList = App.mDaoSession?.orderProductDBDao?.queryBuilder()?.where(OrderProductDBDao.Properties.OrderId.eq(mPendingOrder?.id))?.list()
                    deleteList?.forEach {
                        //然后逐个删除掉
                        //d("deleteList:${CommUtils.gson.toJson(it)}")
                        App.mDaoSession?.orderProductDBDao?.delete(it)
                    }
                    //最后移除改订单
                    App.mDaoSession?.orderDBDao?.delete(mPendingOrder)
                    e.onNext("操作成功!")
                }
            } catch (exe: Exception) {
                d("操作失败:${exe}")
                e.onError(Throwable("操作失败：$exe"))
            }
        })
            .compose(RxUtils.io())
            .compose(RxUtils.aLifecycle(baseActivity))
            .subscribe(object : MyObserver<String>() {
                override fun onNext(t: String) {
                    apiCallBack?.success(t)
                }

                override fun onError(t: Throwable) {
                    ToastUtil.showToast(t.message.toString())
                    apiCallBack?.fail(t)
                }
            })
    }


    /*获取上一个订单*/
    fun getLastOrder(): OrderDB? {
        var list = arrayListOf(OrderDBDao.Properties.OrderType.eq(ORDER_TYPE_NORMAL))//订单
        list.add(OrderDBDao.Properties.UserId.eq(DataApi.mUserId)) //用户id
        var orderDBList = App.mDaoMaster?.newSession()?.queryBuilder(OrderDB::class.java)
            ?.where(WhereCondition.StringCondition("1=1"), *list.toTypedArray())
            ?.orderDesc(OrderDBDao.Properties.PayTime)
            ?.offset(0)?.limit(200)
            ?.list()?.toMutableList()
        var orderDB = orderDBList?.firstOrNull()
        //d("getLastOrder:${CommUtils.gson.toJson(orderDBList)}")
        return orderDB
    }

    private fun d(msg: String) {
        CommUtils.println("SaveOrderApi->", msg)
    }

    //本地数据库订单转线上请求数据
    fun toServerOrderBean(orderDB: OrderDB): ServerOrder {
        return ServerOrder().apply {
            when (orderDB.payType) {
                //0现金   1微会员    2聚合支付
                PAY_TYPE_CASH.toString() -> this.pay_t = "4" //1：微会员支付 2：会员支付 3：聚合支付 4：现金支付
                PAY_TYPE_WETCH_VIP.toString() -> this.pay_t = "1" //1：微会员支付 2：会员支付 3：聚合支付 4：现金支付
                PAY_TYPE_VIP_CARD.toString() -> this.pay_t = "2" //1：微会员支付 2：会员支付 3：聚合支付 4：现金支付
                PAY_TYPE_JUHE.toString() -> this.pay_t = "3" //1：微会员支付 2：会员支付 3：聚合支付 4：现金支付
                PAY_TYPE_SCAN_QR.toString() -> this.pay_t = "5" //1：微会员支付 2：会员支付 3：聚合支付 4：现金支付 5：扫码收款
            }
            this.price = orderDB.realPrice
            this.d_price = orderDB.giftPrice
            this.d_c = String.format("%.2f", orderDB.discountPercent / 100.0)
            this.od_n = orderDB.orderSn
            this.c_time = orderDB.createTimeName
            this.wg = orderDB.totalWeight
            this.data = orderDB.orderProductDBList.map {
                ServerOrderGoods().apply {
                    this.g_id = it.productId?.toString()
                    this.g_nm = it.productName
                    this.wg = it.weight
                    this.unit = (it.unitType + 1).toString()//计价类型 0:计重 1:计数
                    this.price = it.realPrice
                    this.d_price = it.giftPrice
                    this.d_c = String.format("%.2f", it.discountPercent / 100.0)
                    this.sub = it.subTotalPrice
                    this.num = it.weight
                    this.specs = when (it.unitType) {
                        //TODO:这里可能需要调整，因为固定死重量。
                        0 -> "KG"
                        1 -> "件"
                        else -> it.unitName
                    }
                }
            }.toMutableList()
        }
    }

    //本地数据库未支付、现金积分订单转转成线上批量上传数据
    fun toServerOrderBeanBatch(orderDBList: MutableList<OrderDB>): List<ServerOrder> {
        var serverOrderList = orderDBList.map { orderDB ->
            ServerOrder().apply {
                this.pay_t = "4" //1：微会员支付 2：会员支付 3：聚合支付 4：现金支付
                this.price = orderDB.realPrice
                this.od_n = orderDB.orderSn
                this.c_time = orderDB.createTimeName
                this.wg = orderDB.totalWeight
                this.data = orderDB.orderProductDBList.map {
                    ServerOrderGoods().apply {
                        this.g_id = it.productId?.toString()
                        this.g_nm = it.productName
                        this.wg = it.weight
                        this.unit = it.unitType.toString()//计价类型 0:计重 1:计数
                        this.price = it.realPrice
                        this.sub = it.subTotalPrice
                        this.num = it.weight
                        this.specs = when (it.unitType) {
                            //TODO:这里可能需要调整，因为固定死重量。
                            0 -> "KG"
                            1 -> "件"
                            else -> it.unitName
                        }
                    }
                }.toMutableList()
            }
        }
        return serverOrderList
    }

    //获取本地最近未上传订单200数据，现金积分
    fun batchUploadCashOrder(baseActivity: BaseActivity, apiCallBack: ApiCallBack? = null) {
        if (!DataApi.mIsConnectNet) {
            apiCallBack?.fail(Throwable("网络开小差啦!"))
            return
        }
        Observable.create(ObservableOnSubscribe<MutableList<OrderDB>> { e ->
            //查出本地数据
            var list = arrayListOf(OrderDBDao.Properties.OrderType.eq(ORDER_TYPE_NORMAL))//正常订单，非挂单
            //list.add(OrderDBDao.Properties.OrderStatus.eq(ORDER_STATUS_PAYING)) //支付中
            list.add(OrderDBDao.Properties.PayType.eq(PAY_TYPE_CASH)) //现金积分
            list.add(OrderDBDao.Properties.UserId.eq(DataApi.mUserId)) //用户id
            list.add(OrderDBDao.Properties.UploadStatus.notEq(1)) ///0:未上传，1:上传成功,2:上传失败
            var orderList = App.mDaoMaster?.newSession()?.queryBuilder(OrderDB::class.java)
                ?.where(WhereCondition.StringCondition("1=1"), *list.toTypedArray())
                ?.orderDesc(OrderDBDao.Properties.PayTime)
                ?.offset(0)?.limit(200)
                ?.list()
                ?.toMutableList()
                ?: mutableListOf()
            d("转换成服务器提交数据前:${orderList.size}")

            if (orderList.size == 0) {
                //e.onError(Throwable("没有订单可上传啦!"))
                return@ObservableOnSubscribe
            }


            e.onNext(orderList)

        })
            .compose(RxUtils.io())
            .compose(RxUtils.aLifecycle(baseActivity))
            .subscribe(object : MyObserver<MutableList<OrderDB>>() {
                override fun onNext(orderList: MutableList<OrderDB>) {
                    //转换成服务器提交数据
                    var serverOrderList = toServerOrderBeanBatch(orderList)
                    d("转换成服务器提交数据后:${serverOrderList.size}")
                    //提交上传服务器
                    NormalApi.postPay(sortedMapOf(Params.list to CommUtils.gson.toJson(serverOrderList), Params.pay_t to 4), Urls.batchAddOrder)
                        .subscribe(object : DialogObserver<ServerOrderResult>(baseActivity) {
                            override fun onSuccessNext(t: BaseBean<out ServerOrderResult>) {
                                //把订单状态改成已支付。
                                orderList.forEach {
                                    it.uploadStatus = 1
                                    it.orderStatus = ORDER_STATUS_PAID
                                }
                                App.mDaoSession?.orderDBDao?.updateInTx(orderList)
                                apiCallBack?.success(t.msg ?: "上传成功!")
                            }

                            override fun dataIsNull(t: BaseBean<out ServerOrderResult>) {
                                onSuccessNext(t)
                            }

                            override fun onError(t: Throwable) {
                                apiCallBack?.fail(Throwable(t.message))
                                super.onError(t)
                            }
                        })
                    //apiCallBack?.success(t)
                }

                override fun onError(t: Throwable) {
                    ToastUtil.showToast(t.message.toString())
                    apiCallBack?.fail(t)
                }
            })
    }


    //获取本地最近未上传订单总数，现金积分
    fun getNoUploadCashOrderSize(baseActivity: BaseActivity, apiCallBack: ApiCallBack? = null) {
        Observable.create(ObservableOnSubscribe<Int> { e ->
            var list = arrayListOf(OrderDBDao.Properties.OrderType.eq(ORDER_TYPE_NORMAL))//正常订单，非挂单
            //list.add(OrderDBDao.Properties.OrderStatus.eq(ORDER_STATUS_PAYING)) //支付中
            list.add(OrderDBDao.Properties.PayType.eq(PAY_TYPE_CASH)) //现金积分
            list.add(OrderDBDao.Properties.UploadStatus.notEq(1)) ///0:未上传，1:上传成功,2:上传失败
            list.add(OrderDBDao.Properties.UserId.eq(DataApi.mUserId)) //用户id
            var size = App.mDaoMaster?.newSession()?.queryBuilder(OrderDB::class.java)
                ?.where(WhereCondition.StringCondition("1=1"), *list.toTypedArray())
                ?.list()?.size ?: 0
            e.onNext(size)
        })
            .compose(RxUtils.io())
            .compose(RxUtils.aLifecycle(baseActivity))
            .subscribe(object : MyObserver<Int>() {
                override fun onNext(t: Int) {
                    apiCallBack?.success(t)
                }

                override fun onError(t: Throwable) {
                    ToastUtil.showToast(t.message.toString())
                    apiCallBack?.fail(t)
                }
            })
    }

}